package interceptor

import (
	"Gin/app/vo"
	"Gin/config"
	"Gin/middle/jwt"
	"Gin/utils/Redis"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)

var discharged map[string]bool

func HttpInterceptor() gin.HandlerFunc {
	return func(c *gin.Context) {
		if discharged[c.Request.URL.Path] {
			c.Next()
			return
		}
		var token string
		if c.Request.URL.Path == "/ws" {
			token = c.GetHeader("Sec-Websocket-Protocol")
		} else {
			token = c.GetHeader("Authorization")
		}
		if token == "" {
			c.Abort()
			vo.FAIL(nil, config.LoginError, http.StatusInternalServerError, c)
			return
		}
		claims, err := jwt.ParseToken(token)
		if err != nil {
			c.Abort()
			vo.FAIL(nil, config.LoginError, http.StatusInternalServerError, c)
			return
		}
		client := Redis.GetClient()
		r := client.Get(client.Context(), Redis.RootKey+token)
		if time.Now().Before(claims.RegisteredClaims.ExpiresAt.Time) {
			if r != nil {
				newToken := refreshToken(claims)
				vo.OK(newToken, "", 2100, c)
				return
			}
			c.Abort()
			vo.FAIL(nil, config.LoginTimeExpire, http.StatusInternalServerError, c)
			return
		}
		if r != nil {
			client.Expire(client.Context(), Redis.RootKey+token, Redis.KeyExpireTime)
		} else {
			client.Set(client.Context(), Redis.RootKey+token, Redis.KeyExpireTime, Redis.KeyExpireTime)
		}
		c.Next()
	}
}

func refreshToken(c *jwt.Claims) string {
	str, _ := jwt.GenerateToken(c.ID, c.CreatTime, c.UserName)
	return str
}

func AddDischarged(path []string) {
	discharged = make(map[string]bool)
	for _, p := range path {
		discharged[p] = true
	}
}
